package ptij.ADSL.de;

import ptolemy.kernel.*;
import ptolemy.kernel.util.*;
import ptolemy.data.*;
import ptolemy.data.expr.*;
import ptolemy.data.type.*;
import ptolemy.actor.*;
import ptolemy.domains.de.kernel.*;

import java.io.*;
import java.util.Vector;

//////////////////////////////////////////////////////////////////////////
//// BroadBandNet
/**

@author Ivan Jeukens
*/
public class BroadBandNet extends DEActor {
    
    public BroadBandNet(CompositeEntity container, String name) throws
            NameDuplicationException, IllegalActionException {
        super(container, name);

	LS0 = new TypedIOPort(this, "LS0", true, true);
	LS0.setTypeEquals(BaseType.OBJECT);
	LS0.setMultiport(true);
		
        AS0 = new TypedIOPort(this, "AS0", false, true);
	AS0.setTypeEquals(BaseType.OBJECT);
		
	dataTx = new TypedIOPort(this, "dataTx", false, true);
	dataTx.setTypeEquals(BaseType.INT);
	
	AS0_Rate = new Parameter(this, "AS0_Rate", new IntToken(1));
        _nextFireAS0 = 1000.0;
	LS0_Rate = new Parameter(this, "LS0_Rate", new IntToken(1));
        _nextFireLS0 = 1000.0;
    }

    ///////////////////////////////////////////////////////////////////
    ////                     ports and parameters                  ////
    
    public TypedIOPort LS0;
        
    public TypedIOPort dataTx;
    public TypedIOPort AS0;
                
    public Parameter AS0_Rate;
    public Parameter LS0_Rate;

    ///////////////////////////////////////////////////////////////////
    ////                         public methods                    ////

    public void attributeChanged(Attribute attribute)
            throws IllegalActionException {
        if(attribute == AS0_Rate) {
	    IntToken it = (IntToken) AS0_Rate.getToken();
	    _AS0_Rate = it.intValue();
            _nextFireAS0 = 1000.0 / _AS0_Rate;
        }
        else
        if(attribute == LS0_Rate) {
            IntToken it = (IntToken) LS0_Rate.getToken();
            _LS0_Rate = it.intValue();
            _nextFireLS0 = 1000.0 / _LS0_Rate;
        }
	else {
            super.attributeChanged(attribute);
        }
    }

    public void initialize() throws IllegalActionException {
        super.initialize();	

	try {
            File f = new File("test.dat");
            FileInputStream fi = new FileInputStream(f);
            DataInputStream data = new DataInputStream(fi);
            
	    _data = new int[((int) f.length())/4];
	    for(int i = 0;i < _data.length;i++) {
	        _data[i] = data.readInt();
	    }
	    data.close();
	    fi.close();
	} 
	catch(IOException ex) {
	    System.out.println(ex);
	}	
	_counter = 0;

	_LS0Data = new Vector();
	_LS0Counter = 0;

	_nextFire();
    }

    public void fire() throws IllegalActionException {
        if(_nextFire == ((DEDirector) getDirector()).getCurrentTime()) {
            if(_nextFireAS0 == 0) {
                ObjectToken ot = new ObjectToken(new Integer(_data[_counter]));
                AS0.broadcast(ot);
		dataTx.broadcast(new IntToken(0));

  	        _counter = (_counter + 1) % _data.length;
	        _nextFireAS0 = 1000.0 / _AS0_Rate;
  	    }
	
	    if(_nextFireLS0 == 0) {	
		ObjectToken ot = new ObjectToken(new Integer(_data[_counter]));
                LS0.broadcast(ot);
		dataTx.broadcast(new IntToken(1));
		
   	        _counter = (_counter + 1) % _data.length;
  	        _nextFireLS0 = 1000.0 / _LS0_Rate;
 	    }
	    _nextFire();
	}

	ObjectToken ot;
	int [] tmp = null;
        while(LS0.hasToken(1)) {
            ot = (ObjectToken) LS0.get(1);
	    tmp = (int []) ot.getValue();
	    for(int i = 0;i < tmp.length;i++) {
	        _LS0Data.insertElementAt(new Byte((byte)tmp[i]), _LS0Counter);
		_LS0Counter++;
	    }
	}    
    }
        
    public void wrapup() throws IllegalActionException {
        super.wrapup();
	try {
            File f = new File("ls0_c.rx");
            FileOutputStream fo = new FileOutputStream(f);
            DataOutputStream data = new DataOutputStream(fo);
            
	    for(int i = 0;i < _LS0Data.size();i++) {
	        Byte b = (Byte) _LS0Data.elementAt(i);
		data.write(b.byteValue());
	    }
	    data.close();	    
	    fo.close();
	}
	catch(IOException ex) {
	    System.out.println(ex);
	}
    }

    ///////////////////////////////////////////////////////////////////
    ////                         private methods                   ////
    
    private void _nextFire() throws IllegalActionException {    
        double min = 1000.0;
	boolean sched = false;
	
	if(_nextFireAS0 < min) min = _nextFireAS0;	
	if(_nextFireLS0 < min) min = _nextFireLS0;
	
	if(_nextFireAS0 - min == 0) {
            double t = ((DEDirector) getDirector()).getCurrentTime();
	    ((DEDirector) getDirector()).fireAt(this, t + _nextFireAS0);
	    _nextFire = t + _nextFireAS0;
	    sched = true;
	}
	_nextFireAS0 -= min;

	if((sched == false) && (_nextFireLS0 - min == 0))  {
            double t = ((DEDirector) getDirector()).getCurrentTime();	
	    ((DEDirector) getDirector()).fireAt(this, t + _nextFireLS0);
	    _nextFire = t + _nextFireLS0;
	}
	_nextFireLS0 -= min;
    }

    ///////////////////////////////////////////////////////////////////
    ////                         private variables                 ////
    
    private int _AS0_Rate;
    private int _LS0_Rate;
    
    private double _nextFireAS0;
    private double _nextFireLS0;
    private double _nextFire;
        
    private int [] _data;
    private int _counter;

    private Vector _LS0Data;
    private int _LS0Counter;
}
